package com.basker.pisces.domain.value;

import java.util.Calendar;
import java.util.Date;

import org.springframework.util.Assert;

import com.basker.pisces.utils.DateUtils;
import com.basker.pisces.utils.NumberUtils;

/**
 * 表示时长的值
 *
 * @author hangwen
 */
public class DurationValue implements IValueObject {

    public final static DurationValue NULL_Duration = new DurationValue(null, null) {
        @Override
        public Object getDataValue() {
            return null;
        }

        @Override
        public String getPresentValue() {
            return "";
        }
    };

    /**
     * 将一个表达式转换成DurationValue，如1y表示1年，2M表示2个月，10d表示10天
     *
     * @param value
     * @return
     */
    public static DurationValue parse(String value) {
        Assert.hasText(value, "parameter 'value' is required");
        if (value.length() < 2) {
            throw new IllegalArgumentException("parameter 'value':" + value + " is valid");
        }

        int length = value.length();
        String time = value.substring(0, length - 1);
        String pattern = value.substring(length - 1, length);

        return new DurationValue(NumberUtils.parseInt(time), DurationUnit.parse(pattern));

    }

    private DurationUnit unit;
    private Integer time;

    public DurationValue(Integer time, DurationUnit unit) {
        this.time = time;
        this.unit = unit;
    }

    /**
     * 获取start日期时间经过当前时段之后的日期时间
     *
     * @param start
     * @return
     */
    public Date after(Date start) {
        Assert.notNull(start, "parameter 'start' is required");

        return DateUtils.adjust(start, this.unit.getCalendarFieldType(), this.time);
    }

    @Override
    public Object getDataValue() {
        return time;
    }

    @Override
    public String getPresentValue() {
        if (this.isEmpty()) {
            return "";
        }

        return String.valueOf(time) + unit.pattern;
    }

    public Integer getTime() {
        return time;
    }

    public DurationUnit getUnit() {
        return unit;
    }

    @Override
    public boolean isEmpty() {
        return time == null || unit == null;
    }

    public static enum DurationUnit {

        Day("d"), Month("M"), Week("w"), Year("y"), Hour("h"), Minute("m"), Second("s");

        public static DurationUnit parse(String pattern) {
            Assert.hasText(pattern, "parameter 'pattern' is required");

            for (DurationUnit unit : values()) {
                if (pattern.equals(unit.pattern)) {
                    return unit;
                }
            }

            throw new RuntimeException("pattern:" + pattern + " is not support");
        }

        private String pattern;

        DurationUnit(String pattern) {
            this.pattern = pattern;
        }

        /**
         * 获取对应的{@link Calendar}的fieldType
         *
         * @return
         */
        public int getCalendarFieldType() {
            switch (this) {
                case Year:
                    return Calendar.YEAR;
                case Month:
                    return Calendar.MONTH;
                case Week:
                    return Calendar.WEEK_OF_YEAR;
                case Day:
                    return Calendar.DATE;
                case Hour:
                    return Calendar.HOUR;
                case Minute:
                    return Calendar.MINUTE;
                case Second:
                    return Calendar.SECOND;
                default:
                    throw new RuntimeException("invalid DurationUnit '" + this.name() + "'");
            }
        }

        public String getPattern() {
            return pattern;
        }

        @Override
        public String toString() {
            return this.pattern;
        }

    }

}
